package com.pz.cloud.framework.util;

import com.pz.cloud.framework.base.expection.CustomRuntimeException;
import com.pz.cloud.framework.base.model.WorkflowEntity;
import com.pz.cloud.framework.business.workflow.annotation.WorkflowVariable;
import com.pz.cloud.framework.business.workflow.entity.ProcessBind;
import com.pz.cloud.framework.business.workflow.enums.WorkflowEnum;
import com.pz.cloud.framework.business.workflow.model.BaseTaskCallback;
import com.pz.cloud.framework.business.workflow.model.WorkflowModel;
import com.pz.cloud.framework.business.workflow.service.IProcessBindService;
import com.pz.cloud.framework.business.workflow.service.IWorkflowService;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.SpringContextUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 工作流相关工具类
 * @author mzz
 */
@Component
public class WorkflowUtil {
    @Autowired
    private IWorkflowService workflowService;
    @Autowired
    private IProcessBindService processBindService;


    public static WorkflowUtil workflowUtil;

    private static Logger log = LoggerFactory.getLogger(WorkflowUtil.class);

    @PostConstruct
    public void init() {
        workflowUtil = this;
    }

    public static void deleteProcess(String bizId){
        workflowUtil.workflowService.deleteProcessByBizId(bizId,true);
    }

    /**
     * 判断流程是否结束
     * @return
     */
    public static Boolean isProcessEnd(String instanceId){
        return workflowUtil.workflowService.isProcessEnd(instanceId);
    }

    public static void assembleDealFlag(WorkflowEntity workflowEntity){
        workflowUtil.workflowService.assembleDealFlag(workflowEntity);
    }
    public static Integer getDealFlagByBizId(String bizId){
       return workflowUtil.workflowService.getDealFlagByBizId(bizId);
    }
    public static Result submit(WorkflowEntity arg){
        Result result = null;
        try {
            setWorkflowVariable(arg);
            WorkflowModel workflowModel = arg.getWorkflowModel();
            if(StringUtils.isNotEmpty(workflowModel.getOperation())){

                //设置流程所需变量

                String id = BizUtil.getIdFieldValue(arg);
                if(StringUtils.isNotEmpty(id)){
                    workflowModel.setRelatedId(id);
                }

                workflowModel.setRelatedTable(arg.getTableName());
                result  = workflowUtil.workflowService.submit(workflowModel);
                //回调
                String callback = arg.getWorkflowModel().getCallback();
                if(StringUtils.isNotEmpty(callback)){
                    BaseTaskCallback taskCallback = (BaseTaskCallback) SpringContextUtils.getBean(callback);
                    if(taskCallback!=null){
                        taskCallback.execute(arg);
                    }
                }
            }
            return result;
        } catch (IllegalAccessException e) {
            throw new CustomRuntimeException(e);
        }
    }

    public static void setWorkflowVariable(WorkflowEntity arg) throws IllegalAccessException {
        WorkflowModel workflowModel = arg.getWorkflowModel();

        Field[] fields = FieldUtil.getAllFields(arg.getClass());
        for (Field field : fields) {
            if(field.isAnnotationPresent(WorkflowVariable.class)){
                field.setAccessible(true);
                Object value = field.get(arg);
                if(value!=null&&!"".equals(value)){
                    WorkflowVariable workflowVariable = field.getAnnotation(WorkflowVariable.class);
                    WorkflowEnum name = workflowVariable.name();
                    switch (name){
                        case TITLE:
                            workflowModel.setTitle(value.toString());
                            break;
                        case NUMBER:
                            workflowModel.setNumber(value.toString());
                            break;
                    }
                }
            }
        }


        ProcessBind processBind = workflowUtil.processBindService.findProcessBind(arg);
        if(processBind==null){
            List<ProcessBind> processBinds = workflowUtil.processBindService.findByRelatedTable("default");
            if(!CollectionUtils.isEmpty(processBinds)){
                processBind = processBinds.get(0);
            }
        }
        if(processBind!=null){
            workflowModel.setProcessKey(processBind.getProcessKey());
            workflowModel.setProcessBindId(processBind.getId());
            if(StringUtils.isEmpty(workflowModel.getTitle())){
                String titleExpression = processBind.getTitleExpression();
                String reg = "\\$\\{[\\s\\S]*}";
                Pattern pattern =  Pattern.compile(reg);
                Matcher matcher = pattern.matcher(titleExpression);
                while (matcher.find()){
                    String group = matcher.group();
                    String fieldName = group.substring(2, group.length() - 1);

                    Object fieldValue = FieldUtil.getFieldValueByName(arg, fieldName);
                    if(fieldValue!=null){
                        titleExpression = titleExpression.replace(group,fieldValue.toString());
                    }
                }
                workflowModel.setTitle(titleExpression);
            }
        }
    }


}
